/*
 * calculations.h
 *
 *  Created on: Jun 9, 2010
 *      Author: philipp
 */

#ifndef CALCULATOR_H_
#define CALCULATOR_H_


const char * compareTypes(const char * t1, const char * t2){
	//this function returns the greater type of the 2 types specified
	assert(t1 && t2);
	if(strncmp(t1, "float", 100) == 0 && strncmp(t2, "int", 100) == 0)
		return t1;
	else if(strncmp(t1, "int", 100) == 0 && strncmp(t2, "float", 100) == 0)
	    return t2;
	else if(strncmp(t1, "char", 100) == 0 && strncmp(t2, "string", 100) == 0)
		return t2;
	else if(strncmp(t1, "string", 100) == 0 && strncmp(t2, "char", 100) == 0)
	    return t1;
	else{
		return t1;
	}
}


var * multiply(const var* op1, const var* op2){
	if(!checkTypes(op1, op2) && !checkTypes(op2, op1) ) // here float * int and also int * float is compatible
		yyerror("Types are not compatible");
	    //already makes checks if the types are not NULL

	assert(op1->type && op2->type);
	const char * type = compareTypes(op1->type, op2->type);

	var* v;
    if (strncmp(type, "int", 4) == 0) {
        v = newVarInt(NULL, op1->value.i * op2->value.i);
    } else if (strncmp(type, "float", 6) == 0) {
        v = newVarFloat(NULL, op1->value.f * op2->value.f);
    } else {
    	yyerror("type not supported by multiplication operation");
    }

    return v;
}

var * sum(const var* op1, const var* op2){
	if(!checkTypes(op1, op2) && !checkTypes(op2, op1) )
		yyerror("Types are not compatible");
	    //already makes checks if the types are not NULL

	assert(op1->type && op2->type);
    const char * type = compareTypes(op1->type, op2->type);
	var* v;
    if (strncmp(type, "int", 4) == 0) {
        v = newVarInt(NULL, op1->value.i + op2->value.i);
    } else if (strncmp(type, "float", 6) == 0) {
        v = newVarFloat(NULL, op1->value.f + op2->value.f);
    } else {
    	yyerror("type not supported by sum operation");
    }

    return v;
}

var * negate(const var* op1){
	assert(op1->type);
	var* v;
    if (strncmp(op1->type, "int", 4) == 0) {
        v = newVarInt(NULL, -op1->value.i);
    } else if (strncmp(op1->type, "float", 6) == 0) {
        v = newVarFloat(NULL, -op1->value.f);
    } else {
    	yyerror("type not supported by negation operation");
    }

    return v;
}

var * subtract(const var* op1, const var* op2){
	if(!checkTypes(op1, op2) && !checkTypes(op2, op1) )
		yyerror("Types are not compatible");
	    //already makes checks if the types are not NULL

	assert(op1->type && op2->type);
    const char * type = compareTypes(op1->type, op2->type);
	var* v;
    if (strncmp(type, "int", 4) == 0) {
        v = newVarInt(NULL, op1->value.i - op2->value.i);
    } else if (strncmp(type, "float", 6) == 0) {
        v = newVarFloat(NULL, op1->value.f - op2->value.f);
    } else {
    	yyerror("type not supported by subtraction operation");
    }

    return v;
}

var * divide(const var* op1, const var* op2){
	if(!checkTypes(op1, op2) && !checkTypes(op2, op1) )
		yyerror("Types are not compatible");
	    //already makes checks if the types are not NULL

	assert(op1->type && op2->type);
    const char * type = compareTypes(op1->type, op2->type);
	var* v;
    if (strncmp(type, "int", 4) == 0) {
    	if(op2->value.f==0){
        	yyerror("attempted to divide by zero");
        }
        v = newVarInt(NULL, op1->value.i / op2->value.i);
    } else if (strncmp(type, "float", 6) == 0) {
        if(op2->value.f==0){
        	yyerror("attempted to divide by zero");
        }
        v = newVarFloat(NULL, op1->value.f / op2->value.f);
    } else {
    	yyerror("type not supported by division operation");
    }

    return v;
}

var * mod(const var* op1, const var* op2){
	if(!checkTypes(op1, op2) && !checkTypes(op2, op1) )
		yyerror("Types are not compatible");
	    //already makes checks if the types are not NULL

	assert(op1->type && op2->type);
    const char * type = compareTypes(op1->type, op2->type);
	var* v;
    if (strncmp(type, "int", 4) == 0) {
        v = newVarInt(NULL, op1->value.i % op2->value.i);
    }
    else {
    	yyerror("type not supported by modulo operation (only supported by int)");
    }

    return v;
}

#endif /* CALCULATOR_H_ */
